package com.ycy;

import com.fasterxml.jackson.databind.json.JsonMapper;
import com.github.tobato.fastdfs.domain.fdfs.FileInfo;
import com.github.tobato.fastdfs.domain.fdfs.MetaData;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.domain.fdfs.ThumbImageConfig;
import com.github.tobato.fastdfs.domain.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.DefaultFastFileStorageClient;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import javax.security.auth.callback.Callback;
import java.io.*;
import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

@Slf4j
@Service
public class UploadService {

  @Autowired
  @Qualifier("fastFileStorageClient")
  FastFileStorageClient storageClient;

  @Autowired
  private ThumbImageConfig thumbImageConfig;

  /**
   * 上传图片，并且生成缩略图
   * <pre>
   *     缩略图为上传文件名+缩略图后缀 _150x150,如 xxx.jpg,缩略图为 xxx_150x150.jpg
   *
   * 实际样例如下
   *
   * http://localhost:8098/M00/00/17/rBEAAl33pQaAWNQNAAHYvQQn-YE374.jpg
   * http://localhost:8098/M00/00/17/rBEAAl33pQaAWNQNAAHYvQQn-YE374_150x150.jpg
   * </pre>
   */
  public void testUploadImageAndCrtThumbImage() {
    log.info("##上传文件..##");
    Set<MetaData> metaDataSet = createMetaData();
    StorePath path = uploadImageAndCrtThumbImage(TestConstants.CAT_IMAGE_FILE, metaDataSet);
    log.info("上传文件路径{}", path);

    //21:32:14.148 [main] INFO com.ycy.UploadService - 上传文件路径StorePath [group=group1, path=M00/00/00/wKicb2MOEV2AZ7eXAADJbfIXAss313.jpg]

    // 验证获取MetaData
    Set<MetaData> fetchMetaData = storageClient.getMetadata(path.getGroup(), path.getPath());
    assertEquals(fetchMetaData, metaDataSet);

    // 验证获取从文件
    log.info("##获取Metadata## {}", fetchMetaData);
    // 这里需要一个获取从文件名的能力，所以从文件名配置以后就最好不要改了
    String slavePath = thumbImageConfig.getThumbImagePath(path.getPath());
    log.info("缩略图 {}", slavePath);
    // 或者由客户端再记录一下从文件的前缀
    FileInfo slaveFile = storageClient.queryFileInfo(path.getGroup(), slavePath);
    assertNotNull(slaveFile);
    log.info("##获取到从文件##{}", slaveFile);

    storageClient.downloadFile(path.getGroup(), path.getPath(), new DownloadCallback<Object>() {
      @Override
      public Object recv(InputStream ins) throws IOException {

        log.info("##下载文件完成##{}", "ok");

        return null;
      }
    });

  }

  /**
   * 上传文件
   *
   * @param filePath
   * @return
   */
  private StorePath uploadImageAndCrtThumbImage(String filePath, Set<MetaData> metaDataSet) {
    InputStream in = null;
    File file = TestUtils.getFile(filePath);
    String fileExtName = FilenameUtils.getExtension(file.getName());
    long fileSize = file.length();
    try {
      in = TestUtils.getFileInputStream(filePath);
      return storageClient.uploadImageAndCrtThumbImage(in, fileSize, fileExtName, metaDataSet);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    } finally {
      if (null != in) {
        try {
          in.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return null;

  }

  /**
   * 上传图片
   */
  public String uploadImage(byte[] imageByte, String fileExtension, boolean withThumbnail) throws IOException {
    StorePath storePath;
    try (InputStream inputStream = new ByteArrayInputStream(imageByte)) {
      if (withThumbnail) {
        storePath = storageClient.uploadImageAndCrtThumbImage(inputStream, imageByte.length,
                fileExtension, null);
      } else {
        storePath = storageClient.uploadFile(inputStream, imageByte.length,
                fileExtension, null);
      }
    }
    String resAccessUrl = getResAccessUrl(storePath);
    log.info("图片上传成功: {}", resAccessUrl);
    return resAccessUrl;
  }

  /**
   * 上传文件
   *
   * @param file 文件对象
   * @return 文件访问地址
   * @throws IOException 异常
   */
  public String uploadFile(File file) throws IOException {
    StorePath storePath;
    try (FileInputStream inputStream = new FileInputStream(file)) {
      storePath = storageClient.uploadFile(inputStream, file.length(),
              FilenameUtils.getExtension(file.getName()), null);
    }
    return getResAccessUrl(storePath);
  }

  public String uploadFile(ByteArrayOutputStream byteArrayOutputStream, String fileExtension) throws IOException {
    StorePath storePath;
    byte[] bytes = byteArrayOutputStream.toByteArray();
    try (InputStream inputStream = new ByteArrayInputStream(bytes)) {
      storePath = storageClient.uploadFile(inputStream, bytes.length, fileExtension, null);
    }
    return getResAccessUrl(storePath);
  }

  private Set<MetaData> createMetaData() {
    Set<MetaData> metaDataSet = new HashSet<>();
    metaDataSet.add(new MetaData("Author", "tobato"));
    metaDataSet.add(new MetaData("CreateDate", "2016-01-05"));
    metaDataSet.add(new MetaData("desc", "ycy"));
    return metaDataSet;
  }

  /**
   * 封装图片完整URL地址
   *
   * @param storePath 存储路径
   * @return String
   */
  private String getResAccessUrl(StorePath storePath) {
    return storePath.getFullPath();
  }

}
